<?php


namespace app\cms\community\lib\utils\addons\lib;


use app\cms\community\lib\utils\addons\exception\addonsEmptyException;
use app\cms\community\lib\utils\addons\exception\addonsException;
use app\cms\model\addons\addonsModel;
use app\cms\model\buildModel;
use iflow\fileSystem\lib\FileList;
use iflow\Utils\basicTools;

abstract class saveAddonsAbstract {

    /**
     * 文件类型
     * @var array|string[]
     */
    protected array $fileTypes = [
        'zip',
        'ftp',
        'http',
        'git',
        'upload',
        'disk'
    ];

    /**
     * 是否完成解压
     * @var bool
     */
    protected bool $zip = false;


    /**
     * 临时文件存储地址
     * @var string
     */
    protected string $tempPath;

    /**
     * 储存插件地址
     * @var string
     */
    protected string $addonsRootPath;


    /**
     * 插件配置
     * @var array
     */
    protected array $addonsConfig = [];

    /**
     * 临时文件存储文件夹
     * @var string
     */
    protected string $uuid;

    /**
     * 上传临时 (压缩包) 文件存储地址
     * @var string
     */
    protected string $saveTempPath;

    /**
     * saveAddons constructor.
     * @param int $fileType 文件类型
     * @throws addonsEmptyException
     */
    public function __construct(
        protected int $fileType = 0
    ) {
        if (!array_key_exists($this->fileType, $this->fileTypes)) {
            throw new addonsEmptyException('获取插件地址格式错误');
        }

        $this->uuid = (new basicTools()) -> create_uuid();
        $this->tempPath =  app() -> getRunTimePath(). 'store' . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR. $this->uuid;
        $this->addonsRootPath = app() -> getRootPath() . 'app/addons/libs/';
    }

    /**
     * 解压文件
     * @param string $path
     * @return bool
     */
    protected function unZip(string $path): bool
    {
        return $this->zip = unzip($path, $this->tempPath);
    }

    /**
     * 加载插件配置
     * @param string $configPath
     * @return static
     * @throws addonsEmptyException
     */
    protected function loadConfig(string $configPath): static
    {
        if (!file_exists($configPath)) {
            $this->removeAllFile();
            throw new addonsEmptyException('插件配置文件不存在');
        }

        $this->addonsConfig = json_decode(
            file_get_contents($configPath), true
        );

        if (!isset($this->addonsConfig['addons_alis_rule']) || !isset($this->addonsConfig['addons_ns_code'])) {
            $this->removeAllFile();
            throw new addonsEmptyException('插件唯一入口或插件标识码不存在');
        }

        return $this;
    }

    /**
     * 初始化数据库
     * @param string $dbPath
     * @return $this
     */
    protected function initDb(string $dbPath): static {
        if (!is_dir($dbPath)) return $this;
        load_sql_save_to_server(new buildModel(table: 'user_table'), $dbPath);
        return $this;
    }

    /**
     * 将插件信息存入数据库
     * @return $this
     * @throws addonsException
     */
    protected function saveAddonsToDb(): static
    {
        $addonsModel = new addonsModel();
        if ($addonsModel -> getAddonsByCode(
            $this->addonsConfig['addons_ns_code']
        )) {
            $this->removeAllFile();
            throw new addonsException('当前插件已安装');
        }

        $this->addonsConfig['addons_install'] = $this->addonsRootPath;

        $addons = $addonsModel -> findInfo([
            'addons_ns_code' => $this->addonsConfig['addons_ns_code']
        ]);
        if ($addons) {
            unset($this->addonsConfig['addons_ns_code']);
            $addonsModel -> updateInfo($this->addonsConfig, [
                'addons_ns_code' => $this->addonsConfig['addons_ns_code']
            ]);
        } else {
            $addonsModel -> createData($this->addonsConfig);
        }

        return $this;
    }

    /**
     * 保存插件数据
     * @return bool
     * @throws addonsEmptyException
     * @throws addonsException
     */
    public function save(): bool {
        $this -> loadConfig($this->addonsRootPath . '/addons.json');
        $this -> saveAddonsToDb()
              -> initDb($this->addonsRootPath . '/install');
        return true;
    }

    /**
     * 删除临时文件
     * @return $this
     */
    protected function removeTemp(): static
    {
        app(FileList::class) ->  removeDir($this->tempPath);
        return $this;
    }


    /**
     * 删除全部文件
     * @return $this
     */
    public function removeAllFile(): static
    {
        $this->removeTemp();
        app(FileList::class) -> removeDir($this->addonsRootPath);
        return $this;
    }
}